package dreic;

object RISC {

    //########################################################################
    // Word size

    /** The word size */
    val WORD_SIZE = 4;

    //########################################################################
    // Opcodes - instructions with registers

    /**
     * <p>Opcode: integer addition.</p>
     * <b><code>ADD a b c</code></b><br>
     *    <code>R.a = R.b + R.c</code>
     */
    val ADD  =  0;

    /**
     * <p>Opcode: integer subtraction.</p>
     * <b><code>SUB a b c</code></b><br>
     *    <code>R.a = R.b - R.c</code>
     */
    val SUB  =  1;

    /**
     * <p>Opcode: integer multiplication.</p>
     * <b><code>MUL a b c</code></b><br>
     *    <code>R.a = R.b * R.c</code>
     */
    val MUL  =  2;

    /**
     * <p>Opcode: integer division.</p>
     * <b><code>DIV a b c</code></b><br>
     *    <code>R.a = R.b / R.c</code>
     */
    val DIV  =  3;

    /**
     * <p>Opcode: integer modulo.</p>
     * <b><code>MOD a b c</code></b><br>
     *    <code>R.a = R.b % R.c</code>
     */
    val MOD  =  4;

    /**
     * <p>Opcode: integer comparison.</p>
     * <b><code>CMP a b c</code></b><br>
     *    <code>R.a = &lt;a value with the same sign as (R.b - R.c)
     *    but with a possibly different magnitude&gt;</code>
     */
    val CMP  =  5;

    /**
     * <p>Opcode: logical or.</p>
     * <b><code>OR a b c</code></b><br>
     *    <code>R.a = R.b | R.c</code>
     */
    val OR   =  8;

    /**
     * <p>Opcode: logical and.</p>
     * <b><code>AND a b c</code></b><br>
     *    <code>R.a = R.b & R.c</code>
     */
    val AND  =  9;

    /**
     * <p>Opcode: logical bic.</p>
     * <b><code>BIC a b c</code></b><br>
     *    <code>R.a = R.b & ~R.c</code>
     */
    val BIC  = 10;

    /**
     * <p>Opcode: logical xor.</p>
     * <b><code>XOR a b c</code></b><br>
     *    <code>R.a = R.b ^ R.c</code>
     */
    val XOR  = 11;

    /**
     * <p>Opcode: logical shift.</p>
     * <b><code>LSH a b c</code></b><br>
     *    <code>R.a = (R.c &gt; 0) ?
     *      (R.b &lt;&lt; R.c) : (R.b &gt;&gt;&gt; -R.c)</code>
     */
    val LSH  = 12;

    /**
     * <p>Opcode: arithmetic shift.</p>
     * <b><code>ASH a b c</code></b><br>
     *    <code>R.a = (R.c &gt; 0) ?
     *      (R.b &lt;&lt; R.c) : (R.b &gt;&gt; -R.c)</code>
     */
    val ASH  = 13;

    /**
     * <p>Opcode: bound check.</p>
     * <b><code>CHK a c</code></b><br>
     *    raise an error if not <code>(0 &lt;= R.a < R.c)</code>
     */
    val CHK  = 14;

    //########################################################################
    // Opcodes - instructions with register and signed immediate

    /**
     * <p>Opcode: integer addition with signed immediate.</p>
     * <b><code>ADDI a b ic</code></b><br>
     *    <code>R.a = R.b + ic</code>
     */
    val ADDI    = 16;

    /**
     * <p>Opcode: integer subtraction with signed immediate.</p>
     * <b><code>SUBI a b ic</code></b><br>
     *    <code>R.a = R.b - ic</code>
     */
    val SUBI    = 17;

    /**
     * <p>Opcode: integer multiplication with signed immediate.</p>
     * <b><code>MULI a b ic</code></b><br>
     *    <code>R.a = R.b * ic</code>
     */
    val MULI    = 18;

    /**
     * <p>Opcode: integer division with signed immediate.</p>
     * <b><code>DIVI a b ic</code></b><br>
     *    <code>R.a = R.b / ic</code>
     */
    val DIVI    = 19;

    /**
     * <p>Opcode: integer modulo with signed immediate.</p>
     * <b><code>MODI a b ic</code></b><br>
     *    <code>R.a = R.b % ic</code>
     */
    val MODI    = 20;

    /**
     * <p>Opcode: integer comparison with signed immediate.</p>
     * <b><code>CMPI a b ic</code></b><br>
     *    <code>R.a = &lt;a value with the same sign as (R.b - ic)
     *    but with a possibly different magnitude&gt;</code>
     */
    val CMPI    = 21;

    /**
     * <p>Opcode: logical or with signed immediate.</p>
     * <b><code>ORI a b ic</code></b><br>
     *    <code>R.a = R.b | ic</code>
     */
    val ORI     = 24;

    /**
     * <p>Opcode: logical and with signed immediate.</p>
     * <b><code>ANDI a b ic</code></b><br>
     *    <code>R.a = R.b & ic</code>
     */
    val ANDI    = 25;

    /**
     * <p>Opcode: logical bic with signed immediate.</p>
     * <b><code>BICI a b ic</code></b><br>
     *    <code>R.a = R.b & ~ic</code>
     */
    val BICI    = 26;

    /**
     * <p>Opcode: logical xor with signed immediate.</p>
     * <b><code>XORI a b ic</code></b><br>
     *    <code>R.a = R.b ^ ic</code>
     */
    val XORI    = 27;

    /**
     * <p>Opcode: logical shift with signed immediate.</p>
     * <b><code>LSHI a b ic</code></b><br>
     *    <code>R.a = (ic &gt; 0) ?
     *      (R.b &lt;&lt; ic) : (R.b &gt;&gt;&gt; -ic)</code>
     */
    val LSHI    = 28;

    /**
     * <p>Opcode: arithmetic shift with signed immediate.</p>
     * <b><code>ASHI a b ic</code></b><br>
     *    <code>R.a = (ic &gt; 0) ?
     *      (R.b &lt;&lt; ic) : (R.b &gt;&gt; -ic)</code>
     */
    val ASHI    = 29;

    /**
     * <p>Opcode: bound check with signed immediate.</p>
     * <b><code>CHKI a ic</code></b><br>
     *    raise an error if not <code>(0 &lt;= R.a < ic)</code>
     */
    val CHKI    = 30;

    //########################################################################
    // Opcodes - instructions with register and unsigned immediate

    /**
     * <p>Opcode: integer addition with unsigned immediate.</p>
     * <b><code>ADDIU a b uc</code></b><br>
     *    <code>R.a = R.b + uc</code>
     */
    val ADDIU   = 54;

    /**
     * <p>Opcode: integer subtraction with unsigned immediate.</p>
     * <b><code>SUBIU a b uc</code></b><br>
     *    <code>R.a = R.b - uc</code>
     */
    val SUBIU   = 55;

    /**
     * <p>Opcode: integer multiplication with unsigned immediate.</p>
     * <b><code>MULIU a b uc</code></b><br>
     *    <code>R.a = R.b * uc</code>
     */
    val MULIU   = 56;

    /**
     * <p>Opcode: integer division with unsigned immediate.</p>
     * <b><code>DIVIU a b uc</code></b><br>
     *    <code>R.a = R.b / uc</code>
     */
    val DIVIU   = 57;

    /**
     * <p>Opcode: integer modulo with unsigned immediate.</p>
     * <b><code>MODIU a b uc</code></b><br>
     *    <code>R.a = R.b % uc</code>
     */
    val MODIU   = 58;

    /**
     * <p>Opcode: integer comparison with unsigned immediate.</p>
     * <b><code>CMPIU a b uc</code></b><br>
     *    <code>R.a = &lt;a value with the same sign as (R.b - uc)
     *    but with a possibly different magnitude&gt;</code>
     */
    val CMPIU   = 59;

    /**
     * <p>Opcode: logical or with unsigned immediate.</p>
     * <b><code>ORIU a b uc</code></b><br>
     *    <code>R.a = R.b | uc</code>
     */
    val ORIU    = 60;

    /**
     * <p>Opcode: logical and with unsigned immediate.</p>
     * <b><code>ANDIU a b uc</code></b><br>
     *    <code>R.a = R.b & uc</code>
     */
    val ANDIU   = 61;

    /**
     * <p>Opcode: logical bic with unsigned immediate.</p>
     * <b><code>BICIU a b uc</code></b><br>
     *    <code>R.a = R.b & ~uc</code>
     */
    val BICIU   = 62;

    /**
     * <p>Opcode: logical xor with unsigned immediate.</p>
     * <b><code>XORIU a b uc</code></b><br>
     *    <code>R.a = R.b ^ uc</code>
     */
    val XORIU   = 63;

    /**
     * <p>Opcode: bound check with unsigned immediate.</p>
     * <b><code>CHKIU a uc</code></b><br>
     *    raise an error if not <code>(0 &lt;= R.a < uc)</code>
     */
    val CHKIU   = 39;

    //########################################################################
    // Opcodes - load/store instructions

    /**
     * <p>Opcode: load word from memory. The address <code>R.b</code>
     * must be aligned on a word boundary.</p>
     *
     * <b><code>LDW a b ic</code></b><br>
     *    <code>R.a = &lt;word at address R.b + ic&gt;</code>
     */
    val LDW  = 32;

    /**
     * <p>Opcode: load byte from memory.</p>
     *
     * <b><code>LDB a b ic</code></b><br>
     *    <code>R.a = &lt;byte at address R.b + ic&gt;</code>
     */
    val LDB  = 33;

    /**
     * <p>Opcode: pop word from stack. The address <code>R.b</code> must
     * be aligned on a word boundary.</p>
     *
     * <b><code>POP a b ic</code></b><br>
     *    <code>R.a = &lt;word at address R.b&gt;</code><br>
     *    <code>R.b = R.b + ic</code>
     */
    val POP  = 34;

    /**
     * <p>Opcode: store word into memory. The address <code>R.b</code>
     * must be aligned on a word boundary.</p>
     *
     * <b><code>STW a b ic</code></b><br>
     *    <code>&lt;word at address R.b + ic&gt; = R.a</code>
     */
    val STW  = 36;

    /**
     * <p>Opcode: store byte into memory.</p>
     *
     * <b><code>STB a b ic</code></b><br>
     *    <code>&lt;byte at address R.b + ic&gt; = (byte)R.a</code>
     */
    val STB  = 37;

    /**
     * <p>Opcode: push word on stack. The address <code>R.b</code> must
     * be aligned on a word boundary.</p>
     *
     * <b><code>PSH a b ic</code></b><br>
     *    <code>R.b = R.b - ic</code><br>
     *    <code>&lt;word at address R.b&gt; = R.a</code>
     */
    val PSH  = 38;

    //########################################################################
    // Opcodes - control instructions

    /**
     * <p>Opcode: branch if equal.</p>
     * <b><code>BEQ a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a == 0)</code>
     */
    val BEQ  = 40;

    /**
     * <p>Opcode: branch if not equal.</p>
     * <b><code>BNE a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a != 0)</code>
     */
    val BNE  = 41;

    /**
     * <p>Opcode: branch if less than.</p>
     * <b><code>BLT a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a < 0)</code>
     */
    val BLT  = 42;

    /**
     * <p>Opcode: branch if greater or equal.</p>
     * <b><code>BGE a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a >= 0)</code>
     */
    val BGE  = 43;

    /**
     * <p>Opcode: branch if equal less or equal.</p>
     * <b><code>BLE a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a <= 0)</code>
     */
    val BLE  = 44;

    /**
     * <p>Opcode: branch if greater than.</p>
     * <b><code>BGT a oc</code></b><br>
     *    branch to <code>(PC + 4*oc)</code> if <code>(R.a > 0)</code>
     */
    val BGT  = 45;

    /**
     * <p>Opcode: branch to subroutine.</p>
     * <b><code>BSR oc</code></b><br>
     *    <code>R.31 = PC + 4</code><br>
     *    branch to <code>(PC + 4*oc)</code>
     */
    val BSR  = 46;

    /**
     * <p>Opcode: jump to subroutine.</p>
     * <b><code>JSR lc</code></b><br>
     *    <code>R.31 = PC + 4</code><br>
     *    branch to <code>(4*lc)</code>
     */
    val JSR  = 48;

    /**
     * <p>Opcode: jump to return address.</p>
     * <b><code>RET c</code></b><br>
     *    jump to <code>R.c</code>
     */
    val RET  = 49;

    //########################################################################
    // Opcodes - miscellaneous instructions

    /**
     * <p>Opcode: stop execution and return to debugger.</p>
     * <b><code>BREAK</code></b><br>
     *    stop execution and return to debugger
     */
    val BREAK   = 6;

    /**
     * <p>Opcode: invoke a system function.</p>
     * <b><code>SYSCALL a b uc</b></code><br>
     *    invoke system function <code>uc</code> with registers
     *    <code>R.a</code> and <code>R.b</code>
     */
    val SYSCALL = 7;

    /**
     * <p>Opcode: leave the 32-bit signed value in the instruction stream
     */
    val DW = 64;

    //########################################################################
    // System calls - IO read

    /**
     * <p>System call: read one character.</p>
     * <b><code>SYSCALL a 0 SYS_IO_RD_CHR</b></code><br>
     *    <code>R.a = &lt;Unicode of read character or -1 if EOF&gt;</code>
     */
    val SYS_IO_RD_CHR = 1;

    /**
     * <p>System call: read an integer.</p>
     * <b><code>SYSCALL a 0 SYS_IO_RD_INT</b></code><br>
     *    <code>R.a = &lt;value of read integer&gt;</code>
     */
    val SYS_IO_RD_INT = 2;

    //########################################################################
    // System calls - IO write

    /**
     * <p>System call: write one character.</p>
     * <b><code>SYSCALL a 0 SYS_IO_WR_CHR</b></code><br>
     *    <code>&lt;write character with Unicode R.a&gt;</code>
     */
    val SYS_IO_WR_CHR = 6;

    /**
     * <p>System call: write an integer.</p>
     * <b><code>SYSCALL a b SYS_IO_WR_INT</b></code><br>
     *    <code>&lt;write signed value R.a in decimal format and
     *          space padded to width R.b&gt;</code>
     */
    val SYS_IO_WR_INT = 7;

    //########################################################################
    // System calls - garbage collector

    /**
     * <p>System call: initialize the garbage collector.</p>
     *
     * <p>The garbage collector is initialized with an empty heap that
     * starts at address <code>R.a</cod> and with a maximum size of
     * <code>sz = R.b & 0x07FFFFFF</code> words. If <code>sz</code> is
     * zero then the heap extends to the end of the memory.</p>
     *
     * <p>The value <code>sp = R.b &gt;&gt;&gt; 27</code> determines
     * whether there is a stack and which register is the stack
     * pointer: if <code>sp</code> is non-zero, the garbage collector
     * assumes that there is a stack and that <code>R.sp</code> is the
     * stack pointer register. It is assumed that the stack starts at
     * the end of the memory and grows downwards.<p>
     *
     * <p>During a garbage collection, the garbage collector frees all
     * the memory blocks which are not referenced by any live
     * pointer. A live pointer (resp. value) is either a root pointer
     * (resp. value) or a pointer (resp. value) contained in a block
     * referenced by a live pointer. Note that as there is no way to
     * distinguish between pointers and non-pointer values, all values
     * are regarded as pointers. A root value is one that is contained
     * in a register, in the memory below the heap or in the stack. If
     * there is no stack, all the values contained in the memory above
     * the heap are also root values.<p>
     *
     * <b><code>SYSCALL a b SYS_GC_INIT</b></code><br>
     *    <code>&lt;initialize the garbage collector&gt;</code>
     */
    val SYS_GC_INIT = 11;

    /**
     * <p>System call: allocate a memory block from the heap.</p>
     *
     * <p>Allocates a memory block of, at least, <code>R.b</code>
     * bytes from the heap and returns its address in
     * <code>R.a</code>. The allocated memory is zero-initialized and
     * its address is guaranteed to be aligned on a word boundary. If
     * there is not enough free memory, a garbage collection is
     * triggered and if this doesn't free enough memory, an error is
     * raised and the execution stopped.<p>
     *
     * <b><code>SYSCALL a b SYS_GC_ALLOC</b></code><br>
     *    <code>R.a = &lt;address of the newly allocated and
     *          zero-initialized memory block of R.b bytes&gt;</code>
     */
    val SYS_GC_ALLOC = 12;

    //########################################################################
    // System calls - miscellaneous

    /**
     * <p>System call: get memory size.</p>
     * <b><code>SYSCALL a 0 SYS_GET_TOTAL_MEM_SIZE</b></code><br>
     *    <code>R.a = &lt;memory size in bytes&gt;</code>
     */
    val SYS_GET_TOTAL_MEM_SIZE = 13;

    /**
     * <p>System call: flush the output stream.</p>
     * <b><code>SYSCALL 0 0 SYS_IO_FLUSH</b></code><br>
     *    <code>&lt;flush the output stream&gt;</code>
     */
    val SYS_IO_FLUSH = 15;

    /**
     * <p>System call: terminate the emulation.</p>
     * <b><code>SYSCALL a 0 SYS_EXIT</b></code><br>
     *    <code>&lt;terminates the emulation with status code R.a&gt;</code>
     */
    val SYS_EXIT = 19;

    //########################################################################
    // Registers

    /** Register: zero */
    val ZERO =  0;

    /** Register: function result */
    val RES  = 1;

    /** Register: stack pointer */
    val SP   = 30;

    /** Register: return address */
    val LNK  = 31;

    //########################################################################
    // Data structures

    /** String representation of instructions */
    val mnemonics : List[String] = List("add"
											,"sub"
											,"mul"
											,"div"
											,"mod"
											,"cmp"
											,"break"
											,"syscall"
											,"or"
											,"and"
											,"bic"
											,"xor"
											,"lsh"
											,"ash"
											,"chk"
											,""
											,"addi"
											,"subi"
											,"muli"
											,"divi"
											,"modi"
											,"cmpi"
											,""
											,""
											,"ori"
											,"andi"
											,"bici"
											,"xori"
											,"lshi"
											,"ashi"
											,"chki"
											,""
											,"ldw"
											,"ldb"
											,"pop"
											,""
											,"stw"
											,"stb"
											,"psh"
											,""
											,"beq"
											,"bne"
											,"blt"
											,"bge"
											,"ble"
											,"bgt"
											,"bsr"
											,""
											,"jsr"
											,"ret"
											,""
											,""
											,""
											,""
											,"addiu"
											,"subiu"
											,"muliu"
											,"diviu"
											,"modiu"
											,"cmpiu"
											,"oriu"
											,"andiu"
											,"biciu"
											,"xoriu"
											,"chkiu"
											,""
											,""
											,""
											,"dw");
    //########################################################################
}
